package com.lw.websocket.handler;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.net.URI;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * @author Administrator
 * @version 1.0
 * @description:
 * @date 2022/3/23 20:57
 */
@Component
public class MyTextWebsocketHandler extends TextWebSocketHandler {

    private ObjectMapper objectMapper = new ObjectMapper();

    private ConcurrentMap<String,WebSocketSession> allClients=new ConcurrentHashMap();

    /**
     * 当有人和我们的websocket建立连接成功之后执行
     * @param session  当前建立的会话
     * @throws Exception
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        System.err.println("有人和我们连接了");
        //当有人和我们建立连接之后，我们就需要保存一下会话，方便后面获取，后面获取的时候我们需要根据一个关键信息来找会话
        //所以我们必须知道当前的会话属于谁，我们要求用户传递一个标识，我们以这个标识作为唯一的区分,比如我们要求用户在地址的最后一位传递标识
        URI uri = session.getUri();//获取简历连接的时候的地址
        System.err.println(uri);
        String uriString = uri.toString();
        String username = uriString.substring(uriString.lastIndexOf("/") + 1);//裁剪最后一个/后面的内容
        session.getAttributes().put("username",username);//把用户标识保存到session中,下次可以直接获取,避免每次都需要截取数据
        allClients.put(username,session);//以当前用户名作为key，保存会话
    }

    /**
     * 当有人给我们发送数据的时候执行(websocket所有的发送操作都是发给服务端)
     * @param session
     * @param message
     * @throws Exception
     */
    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {

        //收到消息,在这里面我们可以获取到接收者的名字和内容
        //解析数据,有一个key叫toUser代表接收者
        //msg 代表消息内容
        String payload = message.getPayload();//消息的载荷,也就是内容
        System.err.println("收到的内容是:" + payload);
        //根据目标的接收者,找到他的会话
        Map map = objectMapper.readValue(payload, Map.class);//用map接受数据, key就是toUser之类的
        String toUser = (String) map.get("toUser");//找到接收者
        String msg = (String) map.get("msg");//找到内容
        WebSocketSession webSocketSession = allClients.get(toUser);//接收者的会话
        //接收者可能不在线,或者会话关闭了
        if (webSocketSession == null||!webSocketSession.isOpen()) {
            //告诉发消息的人对方不在线,或者保存消息记录等接收者上线后查询一下给他发过去
            session.sendMessage(new TextMessage("对方不在线"));
            return;
        }
        Object username = session.getAttributes().get("username");//从发送者身上找到名字
        //给对方发送内容
        webSocketSession.sendMessage(new TextMessage("收到来自于"+username+"的消息:--->"+msg));

        ///根据会话发送数据
    }

    /**
     * 数据传输出现错误
     * @param session
     * @param exception
     * @throws Exception
     */
    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        super.handleTransportError(session, exception);
    }

    /**
     * 有人和我们关闭连接了
     * @param session
     * @param status
     * @throws Exception
     */
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        Object username = session.getAttributes().get("username");
        allClients.remove(username);//移除会话
    }
}
